{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pose Operation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pose中储存了非常多的信息，同时还提供了接口可以让用户方便的对其中的信息进行修改（采样）。\n",
    "本章节将着重介绍Pose的基本操作方式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PyRosetta-4 2020 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release 2020.23+release.0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 2020-06-04T19:12:24] retrieved from: http://www.pyrosetta.org\n",
      "(C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team.\n",
      "\u001b[0mcore.init: {0} \u001b[0mChecking for fconfig files in pwd and ./rosetta/flags\n",
      "\u001b[0mcore.init: {0} \u001b[0mRosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release r257 2020.23+release.0d6f90a8cb9 0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 http://www.pyrosetta.org 2020-06-04T19:12:24\n",
      "\u001b[0mcore.init: {0} \u001b[0mcommand: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0m'RNG device' seed mode, using '/dev/urandom', seed=-1045734512 seed_offset=0 real_seed=-1045734512 thread_index=0\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0mRandomGenerator:init: Normal mode, seed=-1045734512 RG_type=mt19937\n",
      "\u001b[0mcore.chemical.GlobalResidueTypeSet: {0} \u001b[0mFinished initializing fa_standard residue type set.  Created 980 residue types\n",
      "\u001b[0mcore.chemical.GlobalResidueTypeSet: {0} \u001b[0mTotal time to initialize 0.741039 seconds.\n",
      "\u001b[0mcore.import_pose.import_pose: {0} \u001b[0mFile './data/4R80.clean.pdb' automatically determined to be of type PDB\n",
      "\u001b[0mcore.conformation.Conformation: {0} \u001b[0m\u001b[1m[ WARNING ]\u001b[0m missing heavyatom:  OXT on residue SER:CtermProteinFull 76\n",
      "\u001b[0mcore.conformation.Conformation: {0} \u001b[0m\u001b[1m[ WARNING ]\u001b[0m missing heavyatom:  OXT on residue SER:CtermProteinFull 152\n"
     ]
    }
   ],
   "source": [
    "# 首先依然是从PDB中读入Pose\n",
    "from pyrosetta import init, pose_from_pdb\n",
    "init()\n",
    "pose = pose_from_pdb('./data/4R80.clean.pdb')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1 Pose的创建和复制\n",
    "前几节中提及过，pose是一个容器，理所当然我们可以创建一个空的容器，里面什么都不放。</br>\n",
    "很多时候，我们需要创建空的Pose对象，便于保存当前pose的实例化状态，可作为可回溯点或初始状态，方便反复调用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 通过创建一个新的Pose\n",
    "from pyrosetta import Pose\n",
    "starting_pose = Pose()\n",
    "starting_pose2 = None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此处通过两种方法，将已有的Pose信息放入新的容器里，一种是通过assign函数复制，一种是通过python赋值符号来赋值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PDB file name: ./data/4R80.clean.pdb\n",
      "Total residues: 152\n",
      "Sequence: PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS\n",
      "Fold tree:\n",
      "FOLD_TREE  EDGE 1 76 -1  EDGE 1 77 1  EDGE 77 152 -1 \n",
      "\n",
      "\n",
      "PDB file name: ./data/4R80.clean.pdb\n",
      "Total residues: 152\n",
      "Sequence: PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS\n",
      "Fold tree:\n",
      "FOLD_TREE  EDGE 1 76 -1  EDGE 1 77 1  EDGE 77 152 -1 \n"
     ]
    }
   ],
   "source": [
    "# 方法1：通过assign复制新的构象\n",
    "starting_pose.assign(pose)\n",
    "\n",
    "# 方法2：通过python的直接赋值符号\n",
    "starting_pose2 = pose\n",
    "\n",
    "print(starting_pose)\n",
    "print('\\n')\n",
    "print(starting_pose2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可见，两种方式“看”起来里面都有了新的pose信息。但真的如此么？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "starting_pose 24 residue phi:-91.24043946940483\n",
      "starting_pose2 24 residue phi:170.0\n"
     ]
    }
   ],
   "source": [
    "# 尝试调整mypose中的24号氨基酸phi值:\n",
    "pose.set_phi(24, 170.0)\n",
    "\n",
    "# 查看对starting_pose以及starting_pose2的影响:\n",
    "print(f'starting_pose 24 residue phi:{starting_pose.phi(24)}')\n",
    "print(f'starting_pose2 24 residue phi:{starting_pose2.phi(24)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**结果表明:\n",
    "starting_pose2是用过python直接赋值的Pose并没有复制，而只是pose的一个\"超链接\"符，并没有进行\"复制\"的操作。\n",
    "而通过assign的复制，原始的pose的任何调整都没有对starting_pose造成任何的影响，可见其独立性。**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 链与氨基酸的增减操作\n",
    "先前章节中描述的都是对蛋白质的几何空间做参数的调整，而并不涉及到拓扑结构的改变。在PyRosetta中，对蛋白的结构域进行修改本质上就是对氨基酸的插入和删除。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.1 链的切割处理\n",
    "尽管pose的氨基酸编号是忽略多肽链的分隔的，但是pose中的链依然是根据多肽链的物理结构进行编号的，同理也是从1开始编号。\n",
    "如一个蛋白中有2条链A和B，那么链编号结果即为1和2。其中A对应1号链，B对应2号链，与PDB的链顺序有关（当然A链的顺序如果在后面，那么B链就是1号链）。\n",
    "Pose类中许多的方法可以很方便对链的增减进行操作, 以下2个举例进行说明:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "vector1_std_shared_ptr_core_pose_Pose_t[0x7fbbfc6f2b20, 0x7fbbfcd08d20]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将Pose按照链的数量进行切割\n",
    "pose_list = pose.split_by_chain()\n",
    "pose_list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "此处的pose_list中存放了2个数据，说明链已经被切割成2个独立的pose对象了。\n",
    "\n",
    "通过python的索引，可以获得具体的pose:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "chain1_pose中的氨基酸总数:76\n",
      "chain2_pose中的氨基酸总数:76\n",
      "原始pose中的氨基酸总数:152\n"
     ]
    }
   ],
   "source": [
    "# 获取只含有第一个链的pose\n",
    "chain1_pose = pose.split_by_chain()[1]  # 直接切片索引链号。\n",
    "chain2_pose = pose.split_by_chain()[2]  # 直接切片索引链号。\n",
    "\n",
    "# check\n",
    "print(f'chain1_pose中的氨基酸总数:{chain1_pose.total_residue()}')\n",
    "print(f'chain2_pose中的氨基酸总数:{chain2_pose.total_residue()}')\n",
    "print(f'原始pose中的氨基酸总数:{pose.total_residue()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.2 链的合并处理\n",
    "除了分隔操作，用户还可以通过一些简单的方式把链合并到一个pose中，此处使用append_pose_to_pose函数就可以达到目的。但需要注意，pose中的氨基酸、链的数量变化后，都需要对PDBinfo进行更新。否则PDBinfo的信息与Pose信息不对称。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始chain1_pose中的氨基酸总数:76\n",
      "append之后的chain1_pose中的氨基酸总数:152\n",
      "PDBinfo是否需要被更新:False\n"
     ]
    }
   ],
   "source": [
    "# 两条链的合并;\n",
    "# add binder to pose;\n",
    "from pyrosetta.rosetta.core.pose import append_pose_to_pose\n",
    "print(f'原始chain1_pose中的氨基酸总数:{chain1_pose.total_residue()}')\n",
    "append_pose_to_pose(chain1_pose, chain2_pose)\n",
    "chain1_pose.update_residue_neighbors()\n",
    "chain1_pose.update_pose_chains_from_pdb_chains()\n",
    "chain1_pose.conformation().detect_disulfides()\n",
    "\n",
    "# update pdbinfo; 别忘了更新pdbinfo;\n",
    "# 更新pdb_info; [别忘了]\n",
    "from pyrosetta.rosetta.core.pose import renumber_pdbinfo_based_on_conf_chains\n",
    "renumber_pdbinfo_based_on_conf_chains(pose)\n",
    "\n",
    "print(f'append之后的chain1_pose中的氨基酸总数:{chain1_pose.total_residue()}')\n",
    "chain1_pose.sequence()\n",
    "\n",
    "# 检查PDBinfo是否正确: Returns true if PDBInfo is obsolete and needs updating\n",
    "print(f'PDBinfo是否需要被更新:{pose.pdb_info().obsolete()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.3 氨基酸的删减操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "除了对链的合并之外，我们还可以对链中的氨基酸进行添加、删除的操作！具体的过程是用户需要创建一个独立的氨基酸(residue object)，并将这个氨基酸加载到现有的构像中。\n",
    "加载的方式可以是前置后后置，根据使用的函数不同而定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始氨基酸总数:152\n",
      "原始氨基酸序列:PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS\n",
      "\n",
      "\u001b[0mcore.conformation.Residue: {0} \u001b[0m\u001b[1m[ WARNING ]\u001b[0m Residue connection id changed when creating a new residue at seqpos 1\n",
      "\u001b[0mcore.conformation.Residue: {0} \u001b[0m\u001b[1m[ WARNING ]\u001b[0m ResConnID info stored on the connected residue (residue 2) is now out of date!\n",
      "\u001b[0mcore.conformation.Residue: {0} \u001b[0m\u001b[1m[ WARNING ]\u001b[0m Connection atom name (in src):  C\n",
      "向前添加之后氨基酸总数:153\n",
      "向前添加之后氨基酸序列:APSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 在链的前端添加新的氨基酸或删除氨基酸\n",
    "from pyrosetta.rosetta.core.conformation import ResidueFactory\n",
    "from pyrosetta.rosetta.core.chemical import ChemicalManager\n",
    "\n",
    "print(f'原始氨基酸总数:{pose.total_residue()}')\n",
    "print(f'原始氨基酸序列:{pose.sequence()}\\n')\n",
    "\n",
    "# 向前添加氨基酸\n",
    "chm = ChemicalManager.get_instance()\n",
    "rts = chm.residue_type_set(\"fa_standard\")\n",
    "new_rsd = ResidueFactory.create_residue(rts.name_map('ALA')) # 创建一个residue object\n",
    "pose.prepend_polymer_residue_before_seqpos(new_rsd, 1, True)  # 在第一个氨基酸前添加一个ALA\n",
    "\n",
    "print(f'向前添加之后氨基酸总数:{pose.total_residue()}')\n",
    "print(f'向前添加之后氨基酸序列:{pose.sequence()}\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "向后添加之后氨基酸总数:154\n",
      "向后添加之后氨基酸序列:APSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 向后添加氨基酸\n",
    "last_residue = pose.total_residue()\n",
    "pose.append_polymer_residue_after_seqpos(new_rsd, last_residue, True)  # 在第一个氨基酸前添加一个ALA\n",
    "\n",
    "print(f'向后添加之后氨基酸总数:{pose.total_residue()}')\n",
    "print(f'向后添加之后氨基酸序列:{pose.sequence()}\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "删除之后氨基酸总数:153\n",
      "删除之后氨基酸序列:PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 删除氨基酸\n",
    "pose.delete_polymer_residue(1)  # 删除第一个氨基酸\n",
    "\n",
    "print(f'删除之后氨基酸总数:{pose.total_residue()}')\n",
    "print(f'删除之后氨基酸序列:{pose.sequence()}\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "删除之后氨基酸总数:148\n",
      "删除之后氨基酸序列:EKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 还可以范围性的删除氨基酸\n",
    "pose.delete_residue_range_slow(1,5) # 删除第一个至第五个氨基酸\n",
    "\n",
    "print(f'删除之后氨基酸总数:{pose.total_residue()}')\n",
    "print(f'删除之后氨基酸序列:{pose.sequence()}\\n')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**对拓扑结构操作完后，千万记得PBDinfo更新!!**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PDBinfo是否需要被更新:False\n"
     ]
    }
   ],
   "source": [
    "# 更新pdb_info; [别忘了!]\n",
    "from pyrosetta.rosetta.core.pose import renumber_pdbinfo_based_on_conf_chains\n",
    "\n",
    "renumber_pdbinfo_based_on_conf_chains(pose)  # 更新PDBinfo.\n",
    "\n",
    "# 检查PDBinfo是否正确: Returns true if PDBInfo is obsolete and needs updating\n",
    "print(f'PDBinfo是否需要被更新:{pose.pdb_info().obsolete()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.4 氨基酸类型的调整(突变)\n",
    "除了具体的化学键数据的调整，在PyRosetta中进行氨基酸的类型调整也是很方便的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始氨基酸类型:GLU\n",
      "突变氨基酸中...\n",
      "\u001b[0mcore.scoring.ScoreFunctionFactory: {0} \u001b[0mSCOREFUNCTION: \u001b[32mref2015\u001b[0m\n",
      "\u001b[0mcore.scoring.etable: {0} \u001b[0mStarting energy table calculation\n",
      "\u001b[0mcore.scoring.etable: {0} \u001b[0msmooth_etable: changing atr/rep split to bottom of energy well\n",
      "\u001b[0mcore.scoring.etable: {0} \u001b[0msmooth_etable: spline smoothing lj etables (maxdis = 6)\n",
      "\u001b[0mcore.scoring.etable: {0} \u001b[0msmooth_etable: spline smoothing solvation etables (max_dis = 6)\n",
      "\u001b[0mcore.scoring.etable: {0} \u001b[0mFinished calculating energy tables.\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/hbonds/ref2015_params/HBPoly1D.csv\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/hbonds/ref2015_params/HBFadeIntervals.csv\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/hbonds/ref2015_params/HBEval.csv\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/hbonds/ref2015_params/DonStrength.csv\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/hbonds/ref2015_params/AccStrength.csv\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/rama/fd/all.ramaProb\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/rama/fd/prepro.ramaProb\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/omega/omega_ppdep.all.txt\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/omega/omega_ppdep.gly.txt\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/omega/omega_ppdep.pro.txt\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/omega/omega_ppdep.valile.txt\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/P_AA_pp/P_AA\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/P_AA_pp/P_AA_n\n",
      "\u001b[0mcore.scoring.P_AA: {0} \u001b[0mshapovalov_lib::shap_p_aa_pp_smooth_level of 1( aka low_smooth ) got activated.\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/P_AA_pp/shapovalov/10deg/kappa131/a20.prop\n",
      "\u001b[0mcore.pack.task: {0} \u001b[0mPacker task: initialize from command line()\n",
      "\u001b[0mbasic.io.database: {0} \u001b[0mDatabase file opened: scoring/score_functions/elec_cp_reps.dat\n",
      "\u001b[0mcore.scoring.elec.util: {0} \u001b[0mRead 40 countpair representative atoms\n",
      "\u001b[0mcore.pack.dunbrack.RotamerLibrary: {0} \u001b[0mshapovalov_lib_fixes_enable option is true.\n",
      "\u001b[0mcore.pack.dunbrack.RotamerLibrary: {0} \u001b[0mshapovalov_lib::shap_dun10_smooth_level of 1( aka lowest_smooth ) got activated.\n",
      "\u001b[0mcore.pack.dunbrack.RotamerLibrary: {0} \u001b[0mBinary rotamer library selected: /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database/rotamer/shapovalov/StpDwn_0-0-0/Dunbrack10.lib.bin\n",
      "\u001b[0mcore.pack.dunbrack.RotamerLibrary: {0} \u001b[0mUsing Dunbrack library binary file '/opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database/rotamer/shapovalov/StpDwn_0-0-0/Dunbrack10.lib.bin'.\n",
      "\u001b[0mcore.pack.dunbrack.RotamerLibrary: {0} \u001b[0mDunbrack 2010 library took 0.179004 seconds to load from binary\n",
      "\u001b[0mcore.pack.pack_rotamers: {0} \u001b[0mbuilt 78 rotamers at 5 positions.\n",
      "\u001b[0mcore.pack.pack_rotamers: {0} \u001b[0mRequesting all available threads for interaction graph computation.\n",
      "\u001b[0mcore.pack.interaction_graph.interaction_graph_factory: {0} \u001b[0mInstantiating PDInteractionGraph\n",
      "\u001b[0mbasic.thread_manager.RosettaThreadManager: {?} \u001b[0mCreating a thread pool of 1 threads.\n",
      "\u001b[0mbasic.thread_manager.RosettaThreadPool: {?} \u001b[0mLaunched 0 new threads.\n",
      "\u001b[0mcore.pack.rotamer_set.RotamerSets: {0} \u001b[0mCompleted interaction graph pre-calculation in 1 available threads (1 had been requested).\n",
      "突变后氨基酸类型:ALA\n"
     ]
    }
   ],
   "source": [
    "# 调整氨基酸的类型\n",
    "from pyrosetta.toolbox import mutate_residue\n",
    "print(f'原始氨基酸类型:{pose.residue(1).name()}')\n",
    "print('突变氨基酸中...')\n",
    "mutate_residue(pose, 1, 'A', 9.0)  # 1 代表氨基酸突变的pose编号，9.0代表对氨基酸附近9埃范围内的氨基酸进行侧链优化，适应新的突变。\n",
    "print(f'突变后氨基酸类型:{pose.residue(1).name()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.自定义信息\n",
    "Pose中含有让用户自定义写入任何信息的功能，比如在程序设计过程中，中间生成的临时数值或字符都可以写入到PoseExtraScore中，这些信息会随着Pose一并输出到PDB或则Silent文件中，在后续的分析和处理的过程中非常方便。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n",
      "120.5\n"
     ]
    }
   ],
   "source": [
    "# 给pose加入额外的信息: 比如filter计算的值就可以储存.\n",
    "from pyrosetta.rosetta.core.pose import setPoseExtraScore, getPoseExtraScore\n",
    "\n",
    "setPoseExtraScore(pose, \"distance\", 1.0)\n",
    "setPoseExtraScore(pose, \"angle\", 120.5)\n",
    "\n",
    "# 提取信息\n",
    "print(getPoseExtraScore(pose, 'distance'))\n",
    "print(getPoseExtraScore(pose, 'angle'))  # 目前有bug，但是信息已经储存在pose中了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyrosetta",
   "language": "python",
   "name": "pyrosetta"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
